package com.anlu.comet.servlet3;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.DeferredResult;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 为什么使用DeferredResult？
 Controller处理耗时任务，并且需要耗时任务的返回结果时；

 当一个请求到达API接口，如果该API接口的return返回值是DeferredResult，在没有超时或者DeferredResult对象设置setResult时，
 接口不会返回，但是Servlet容器线程会结束，DeferredResult另起线程来进行结果处理(即这种操作提升了服务短时间的吞吐能力)，
 并setResult，如此以来这个请求不会占用服务连接池太久，如果超时或设置setResult，接口会立即返回。

 使用DeferredResult的流程：

 浏览器发起异步请求
 请求到达服务端被挂起
 向浏览器进行响应，分为两种情况：
 3.1 调用DeferredResult.setResult()，请求被唤醒，返回结果
 3.2 超时，返回一个你设定的结果
 浏览得到响应，再次重复1，处理此次响应结果


 给人一种异步处理业务，但是却同步返回的感觉。
 */
@Controller
@RequestMapping(produces="text/html;charset=UTF-8")
/*记得要在WebInitializer中增加servlet.setAsyncSupported(true);*/
public class PushNewsController {

    private ExecutorService executorService = Executors.newFixedThreadPool(1);

    @RequestMapping("/pushnews")
    public String news(){
        return "pushNews";
    }


    @RequestMapping(value="/realTimeNews")
    @ResponseBody
    public DeferredResult<String> realtimeNews(HttpServletRequest request){
        final DeferredResult<String> dr= new DeferredResult<String>();
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                int index = new Random().nextInt(Const.NEWS.length);
                dr.setResult(Const.NEWS[index]);
            }
        });
        return dr;
    }


}
